<?php
/**
 * Zhub - A PHP Framework For API Developer
 *
 * This file is part of the Zhub package.
 *
 * (c) YiLong Fan <fantiq@163.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @author fanyilong <fantiq@163.com>
 * @copyright 2017 fanyilong. All rights reserved.
 * @package Zhub
 * @date 18-3-8
 */

namespace Zhub\DataBase\Grammar;


class Condition
{
    const EQ = '=';

    const NEQ = '<>';

    const GT = '>';

    const LT = '<';

    const GE = '>=';

    const LE = '<=';

    const AND = 'AND';

    const OR = 'OR';

    private static $instance = null;

    private $expr = null;

    public static function copy($role, $key, $val, $ope)
    {
        if (!self::$instance) {
            self::$instance = new self();
        }
        $instance = clone self::$instance;
        $role ? self::exprTpl($instance, $key, $ope, $val) : self::stmtTpl($instance, $key, $ope, $val);
        return $instance;
    }
    public static function stmtTpl($instance, $field, $operate, $value)
    {
        $instance->role = 0b0;
        $instance->expr = "$field $operate :$field";
        // bind
    }

    public static function exprTpl($instance, $left, $logic, $right)
    {
        $instance->role = 0b1;
        $instance->expr = self::handleNest($left, $instance) . " $logic " . self::handleNest($right, $instance);
    }

    protected static function handleNest($expr, $instance)
    {
        return $instance->role ? $expr : "($expr)";
    }

    public function eq($field, $value)
    {
        return self::copy(0, $field, $value, self::EQ);
    }
    public function ne($field, $value)
    {
        return self::copy(0, $field, $value, self::NEQ);
    }
    public function gt($field, $value)
    {
        return self::copy(0, $field, $value, self::GT);
    }
    public function lt($field, $value)
    {
        return self::copy(0, $field, $value, self::LT);
    }
    public function ge($field, $value)
    {
        return self::copy(0, $field, $value, self::GE);
    }
    public function le($field, $value)
    {
        return self::copy(0, $field, $value, self::LE);
    }

    public function and($left, $right)
    {
        return self::copy(1, $left, $right, self::AND);

    }
    public function or($left, $right)
    {
        return self::copy(1, $left, $right, self::OR);

    }

    public function __toString():string
    {
        return $this->expr;
    }
}

$condition = new Condition();
echo $condition->and(
    $condition->eq('foo', 'name'),
    $condition->or(
        $condition->gt('age', 20),
        $condition->lt('age', 40)
    )
);